diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c
index 53b79c5..7980be0 100644
--- a/drivers/pci/host/pci-mvebu.c
+++ b/drivers/pci/host/pci-mvebu.c
@@ -51,7 +51,14 @@
 	 PCIE_CONF_ADDR_EN)
 #define PCIE_CONF_DATA_OFF	0x18fc
 #define PCIE_MASK_OFF		0x1910
+#define  PCIE_MASK_PM_PME		BIT(28)
 #define  PCIE_MASK_ENABLE_INTS          0x0f000000
+#define  PCIE_MASK_ERR_COR		BIT(18)
+#define  PCIE_MASK_ERR_NONFATAL		BIT(17)
+#define  PCIE_MASK_ERR_FATAL		BIT(16)
+#define  PCIE_MASK_FERR_DET		BIT(10)
+#define  PCIE_MASK_NFERR_DET		BIT(9)
+#define  PCIE_MASK_CORERR_DET		BIT(8)
 #define PCIE_CTRL_OFF		0x1a00
 #define  PCIE_CTRL_X1_MODE		0x0001
 #define PCIE_STAT_OFF		0x1a04
@@ -455,6 +462,54 @@ static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port)
 			       MVEBU_MBUS_NO_REMAP);
 }
 
+static void mvebu_pcie_handle_irq_change(struct mvebu_pcie_port *port)
+{
+	u32 reg, old;
+	u16 devctl, rtctl;
+
+	/*
+	 * Errors from downstream devices:
+	 *  bridge control register SERR: enables reception of errors
+	 * Errors from this device, or received errors:
+	 *  command SERR: enables ERR_NONFATAL and ERR_FATAL messages
+	 *   => when enabled, these conditions also flag SERR in status register
+	 *  devctl CERE: enables ERR_CORR messages
+	 *  devctl NFERE: enables ERR_NONFATAL messages
+	 *  devctl FERE: enables ERR_FATAL messages
+	 * Enabled messages then have three paths:
+	 *  1. rtctl: enables system error indication
+	 *  2. root error status register updated
+	 *  3. root error command register: forwarding via MSI
+	 */
+	old = mvebu_readl(port, PCIE_MASK_OFF);
+	reg = old & ~(PCIE_MASK_PM_PME | PCIE_MASK_FERR_DET |
+		      PCIE_MASK_NFERR_DET | PCIE_MASK_CORERR_DET |
+		      PCIE_MASK_ERR_COR | PCIE_MASK_ERR_NONFATAL |
+		      PCIE_MASK_ERR_FATAL);
+
+	devctl = port->bridge.pcie_devctl;
+	if (devctl & PCI_EXP_DEVCTL_FERE)
+		reg |= PCIE_MASK_FERR_DET | PCIE_MASK_ERR_FATAL;
+	if (devctl & PCI_EXP_DEVCTL_NFERE)
+		reg |= PCIE_MASK_NFERR_DET | PCIE_MASK_ERR_NONFATAL;
+	if (devctl & PCI_EXP_DEVCTL_CERE)
+		reg |= PCIE_MASK_CORERR_DET | PCIE_MASK_ERR_COR;
+	if (port->bridge.command & PCI_COMMAND_SERR)
+		reg |= PCIE_MASK_FERR_DET | PCIE_MASK_NFERR_DET |
+		       PCIE_MASK_ERR_FATAL | PCIE_MASK_ERR_NONFATAL;
+
+	if (!(port->bridge.bridgectrl & PCI_BRIDGE_CTL_SERR))
+		reg &= ~(PCIE_MASK_ERR_COR | PCIE_MASK_ERR_NONFATAL |
+			 PCIE_MASK_ERR_FATAL);
+
+	rtctl = port->bridge.pcie_rtctl;
+	if (rtctl & PCI_EXP_RTCTL_PMEIE)
+		reg |= PCIE_MASK_PM_PME;
+
+	if (old != reg)
+		mvebu_writel(port, reg, PCIE_MASK_OFF);
+}
+
 /*
  * Initialize the configuration space of the PCI-to-PCI bridge
  * associated with the given PCIe interface.
@@ -478,6 +533,7 @@ static void mvebu_sw_pci_bridge_init(struct mvebu_pcie_port *port)
 
 	/* Add capabilities */
 	bridge->status = PCI_STATUS_CAP_LIST;
+	bridge->bridgectrl = PCI_BRIDGE_CTL_SERR;
 }
 
 /*
@@ -550,7 +606,7 @@ static int mvebu_sw_pci_bridge_read(struct mvebu_pcie_port *port,
 
 	case PCI_INTERRUPT_LINE:
 		/* LINE PIN MIN_GNT MAX_LAT */
-		*value = 0;
+		*value = bridge->bridgectrl << 16;
 		break;
 
 	case PCISWCAP_EXP_LIST_ID:
@@ -599,6 +655,16 @@ static int mvebu_sw_pci_bridge_read(struct mvebu_pcie_port *port,
 		*value = mvebu_readl(port, PCIE_RC_RTSTA);
 		break;
 
+	case 0x100 ... 0x128:
+		*value = mvebu_readl(port, where & ~3);
+		break;
+
+	case 0x100 + PCI_ERR_ROOT_COMMAND:
+	case 0x100 + PCI_ERR_ROOT_STATUS:
+	case 0x100 + PCI_ERR_ROOT_ERR_SRC:
+		*value = 0;
+		break;
+
 	/* PCIe requires the v2 fields to be hard-wired to zero */
 	case PCISWCAP_EXP_DEVCAP2:
 	case PCISWCAP_EXP_DEVCTL2:
@@ -629,7 +695,7 @@ static int mvebu_sw_pci_bridge_write(struct mvebu_pcie_port *port,
 				     unsigned int where, int size, u32 value)
 {
 	struct mvebu_sw_pci_bridge *bridge = &port->bridge;
-	u32 mask, reg;
+	u32 mask, reg, old;
 	int err;
 
 	if (size == 4)
@@ -649,8 +715,7 @@ static int mvebu_sw_pci_bridge_write(struct mvebu_pcie_port *port,
 
 	switch (where & ~3) {
 	case PCI_COMMAND:
-	{
-		u32 old = bridge->command;
+		old = bridge->command;
 
 		if (!mvebu_has_ioport(port))
 			value &= ~PCI_COMMAND_IO;
@@ -660,8 +725,9 @@ static int mvebu_sw_pci_bridge_write(struct mvebu_pcie_port *port,
 			mvebu_pcie_handle_iobase_change(port);
 		if ((old ^ bridge->command) & PCI_COMMAND_MEMORY)
 			mvebu_pcie_handle_membase_change(port);
+		if ((old ^ bridge->command) & PCI_COMMAND_SERR)
+			mvebu_pcie_handle_irq_change(port);
 		break;
-	}
 
 	case PCI_BASE_ADDRESS_0 ... PCI_BASE_ADDRESS_1:
 		bridge->bar[((where & ~3) - PCI_BASE_ADDRESS_0) / 4] = value;
@@ -690,6 +756,17 @@ static int mvebu_sw_pci_bridge_write(struct mvebu_pcie_port *port,
 		mvebu_pcie_handle_iobase_change(port);
 		break;
 
+	case PCI_INTERRUPT_LINE:
+		value >>= 16;
+		old = bridge->bridgectrl;
+		/* PCIe only has three bits here */
+		bridge->bridgectrl = value & (PCI_BRIDGE_CTL_BUS_RESET |
+					      PCI_BRIDGE_CTL_SERR |
+					      PCI_BRIDGE_CTL_PARITY);
+		if ((old ^ bridge->bridgectrl) & PCI_BRIDGE_CTL_SERR)
+			mvebu_pcie_handle_irq_change(port);
+		break;
+
 	case PCI_PRIMARY_BUS:
 		bridge->primary_bus             = value & 0xff;
 		bridge->secondary_bus           = (value >> 8) & 0xff;
@@ -699,6 +776,14 @@ static int mvebu_sw_pci_bridge_write(struct mvebu_pcie_port *port,
 		break;
 
 	case PCISWCAP_EXP_DEVCTL:
+		old = bridge->pcie_devctl;
+		bridge->pcie_devctl = value & (PCI_EXP_DEVCTL_FERE |
+					       PCI_EXP_DEVCTL_NFERE |
+					       PCI_EXP_DEVCTL_CERE |
+					       PCI_EXP_DEVCTL_URRE);
+		if (bridge->pcie_devctl ^ old)
+			mvebu_pcie_handle_irq_change(port);
+
 		/*
 		 * Armada370 data says these bits must always
 		 * be zero when in root complex mode.
@@ -739,10 +824,24 @@ static int mvebu_sw_pci_bridge_write(struct mvebu_pcie_port *port,
 		mvebu_writel(port, value, PCIE_CAP_PCIEXP + PCI_EXP_LNKCTL);
 		break;
 
+	case PCISWCAP_EXP_RTCTL:
+		old = bridge->pcie_rtctl;
+		bridge->pcie_rtctl = value & (PCI_EXP_RTCTL_SECEE |
+					      PCI_EXP_RTCTL_SENFEE |
+					      PCI_EXP_RTCTL_SEFEE |
+					      PCI_EXP_RTCTL_PMEIE);
+		if (bridge->pcie_rtctl ^ old)
+			mvebu_pcie_handle_irq_change(port);
+		break;
+
 	case PCISWCAP_EXP_RTSTA:
 		mvebu_writel(port, value, PCIE_RC_RTSTA);
 		break;
 
+	case 0x100 ... 0x128:
+		mvebu_writel(port, value, where & ~3);
+		break;
+
 	default:
 		break;
 	}
